package compoundDB.gui;

import java.awt.Toolkit;

import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;


/**
 * An extension of JTextField, used for restricting user input to only allow
 * characters valid for a file name.
 * 
 * @author Michael Pell, Solutions Plus, Inc.
 */
@SuppressWarnings("serial")
public class JTextFieldFileName extends JTextField
{
	/** Default constructor, sets accepted character to alpha numeric. */
	public JTextFieldFileName()
	{
		super();
		this.setDocument(new JTextFieldFileNameFilter(8, 3));
	}
	/**
	 * Default to alpha numeric chars, specify a maximum file name length and
	 * extension length
	 */
	public JTextFieldFileName(int maxFileNameLength, int maxExtensionLength)
	{
		super();
		this.setDocument(new JTextFieldFileNameFilter(maxFileNameLength, maxExtensionLength));
	}
	/**
	 * Default to alpha numeric chars, specify a maximum file name length , and
	 * set allow or disallow spaces. Do not check for an extension. Do not allow
	 * periods.
	 */
	public JTextFieldFileName(int maxFileNameLength, boolean allowSpaces, boolean allowPeriods)
	{
		super();
		this.setDocument(new JTextFieldFileNameFilter(maxFileNameLength, allowSpaces, allowPeriods));
	}
	/**
	 * Default to alpha numeric chars, specify a maximum file name length , and
	 * set allow or disallow spaces. Do not check for an extension. Do not allow
	 * periods. Allow or not allow upper case chars.
	 */
	public JTextFieldFileName(int maxFileNameLength, boolean allowSpaces, boolean allowPeriods, boolean allowUpperCase)
	{
		super();
		this.setDocument(new JTextFieldFileNameFilter(maxFileNameLength, allowSpaces, allowPeriods, allowUpperCase));
	}
}
/**
 * This JTextField allows for special filtering of what text can be entered.
 * It is specifically used for allowing the user to enter a file name using the 
 * DOS 8.3 format.
 * Spaces may be allowed or disallowed.
 * Valid characters may be specified, alphanumeric is the default.
 * A max file name length and max extension length may be specified.
 * By default only allows 1 "." in the file name.
 *
 * @author  Michael Pell, Solutions Plus, Inc.
 * @author This class was based upon Real Gagnon's (real.gagnon@tactika.com) work, found at
 * http://codeguru.earthweb.com/java/ *
 */
@SuppressWarnings("serial")
 class JTextFieldFileNameFilter extends PlainDocument
{
	public static final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz._";
	public static final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.";
	public static final String ALPHA = LOWERCASE + UPPERCASE;
	public static final String NUMERIC = "0123456789";
	public static final String ALPHA_NUMERIC = ALPHA + NUMERIC;

	private static boolean DEBUG = false;

	private int maxFileNameLength = -1; // -1 means that we're not checking this
										// length
	private int maxExensionLength = -1; // -1 means that we're not checking this
										// length
	//private boolean spacesAllowed = false;
	//private String requiredPrefix = null;
	//private String requiredSuffix = null;
	private boolean allowExtensionChange = true;
	private boolean multiplePeriodsAllowed = false; // not yet implemented
	protected String acceptedChars = null;
	private boolean allowPeriods = true;

	/** Default constructor, sets accepted character to alpha numeric. */
	public JTextFieldFileNameFilter()
	{
		this(ALPHA_NUMERIC);
	}

	/**
	 * Default to alpha numeric chars, specify a maximum file name length and
	 * extension length
	 */
	public JTextFieldFileNameFilter(int aMaxFileNameLength, int aMaxExtensionLength)
	{
		this(ALPHA_NUMERIC);
		this.maxFileNameLength = aMaxFileNameLength;
		this.maxExensionLength = aMaxExtensionLength;
	}

	/**
	 * Default to alpha numeric chars, specify a maximum file name length and
	 * extension length, and set allow or disallow spaces.
	 */
	public JTextFieldFileNameFilter(int aMaxFileNameLength, int aMaxExtensionLength, boolean spacesAllowedArg)
	{
		this(aMaxFileNameLength, aMaxExtensionLength);
		//this.spacesAllowed = spacesAllowedArg;
	}

	/**
	 * Default to alpha numeric chars, specify a maximum file name length , and
	 * set allow or disallow spaces. Do not check for an extension. Do not allow
	 * periods.
	 */
	public JTextFieldFileNameFilter(int aMaxFileNameLength, boolean spacesAllowedArg, boolean allowPeriodArg)
	{
		this(ALPHA_NUMERIC);
		this.maxFileNameLength = aMaxFileNameLength;
		this.allowExtensionChange = false;
		//this.spacesAllowed = spacesAllowedArg;
		this.allowPeriods = allowPeriodArg;
	}

	/**
	 * Default to alpha numeric chars, specify a maximum file name length , and
	 * set allow or disallow spaces. Do not check for an extension. Do not allow
	 * periods. Allow or not allow upper case chars.
	 */
	public JTextFieldFileNameFilter(int aMaxFileNameLength, boolean spacesAllowedArg, boolean allowPeriodArg, boolean allowUpperCase)
	{
		this(JTextFieldFileNameFilter.LOWERCASE +JTextFieldFileNameFilter.UPPERCASE+ JTextFieldFileNameFilter.NUMERIC);
		this.maxFileNameLength = aMaxFileNameLength;
		this.allowExtensionChange = false;
		//this.spacesAllowed = spacesAllowedArg;
		this.allowPeriods = allowPeriodArg;
	}

	/** Assign your own accepted characters. */
	public JTextFieldFileNameFilter(String acceptedchars)
	{
		acceptedChars = acceptedchars;
	}

	/**
	 * Overrides the superclass. This is where the rules are implemented for
	 * filtering user input.
	 */
	public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException
	{
		try
		{
			if (str == null)
			{
				super.insertString(offset, str, attr);
				return;
			}
			if (acceptedChars.equals(UPPERCASE))
				str = str.toUpperCase();
			else if (acceptedChars.equals(LOWERCASE))
				str = str.toLowerCase();

			// Ensure user input is a valid character, return if not valid
			for (int i = 0; i < str.length(); i++)
			{
				if (acceptedChars.indexOf(String.valueOf(str.charAt(i))) == -1)
					return;
			}

			// If we get here, then the user input is valid.

			String allText = this.getText(0, this.getLength());
			int indexOfPeriod = allText.indexOf(".");
			if (!allowPeriods && str.equals("."))
			{
				// Periods are not allowed
				Toolkit.getDefaultToolkit().beep();
				return;
			}
			// only allow 1 period
			if (!multiplePeriodsAllowed && str.equals("."))
			{
				for (int i = 0; i < allText.length(); i++)
				{
					if (allText.charAt(i) == '.')
					{
						// more than 1 period was found, so report error and
						// return
						Toolkit.getDefaultToolkit().beep();
						return;
					}
				}
			}
			if (DEBUG)
			{
				System.out.println("indexOfPeriod is " + indexOfPeriod);
				System.out.println("string argument is " + str);
				System.out.println("allText = " + allText);
				System.out.println("offset argument is = " + offset);
			}

			// Parse out filename and extension

			String filename = "";
			String extension = "";
			if (indexOfPeriod > 0)
				// it coulb be in the first position
				filename = allText.substring(0, indexOfPeriod); // -1
			else if (indexOfPeriod == -1)
				// if no period, then all text is a filename
				filename = allText;

			// if the first character is not alpha, then return
			// if (ALPHA.indexOf(str.valueOf(filename.charAt(0))) == -1)
			// return;

			if (indexOfPeriod != -1 && indexOfPeriod < allText.length())
				// it could be the last position
				extension = allText.substring(indexOfPeriod + 1, allText.length()); // or
																					// if
																					// indexOfPeriod
																					// ==-1,
																					// there
																					// is
																					// no
																					// extension

			if (DEBUG)
			{
				System.out.println("Filename = " + filename);
				System.out.println("Extension = " + extension);
			}

			// now decide if the user is entering a filename or extension

			if (maxFileNameLength != -1 && indexOfPeriod == -1 || offset <= indexOfPeriod) // entering
																							// a
																							// filename
			{
				if (filename.length() >= maxFileNameLength) // will it be too
															// long?
				{
					if (indexOfPeriod == -1 && str.equals(".")) // allow this to
																// happen, its
																// the only
																// period
					{
						super.insertString(offset, str, attr);
						return;
					}
					else
					{
						// We've reached the max filename length,
						// report an error and don't let the user add this
						// character
						Toolkit.getDefaultToolkit().beep();
						return;
					}
				}
				else
				{
					// the entered text (fileName) is valid, so pass on to my
					// super
					super.insertString(offset, str, attr);
					return;
				}
			}
			else
			{
				if (indexOfPeriod != -1 && offset >= indexOfPeriod)
				// entering an extension

				{
					if (allowExtensionChange)
					{
						if (extension.length() >= maxExensionLength)
						{
							// We've reached the max extension length,
							// report an error and don't let the user add this
							// character
							Toolkit.getDefaultToolkit().beep();
							return;
						}
					}
					else
					{
						// We're not allowing the extension to be changed
						// report an error and don't let the user add this
						// character
						Toolkit.getDefaultToolkit().beep();
						return;
					}
				}
			}
			super.insertString(offset, str, attr);
		}
		catch (java.lang.StringIndexOutOfBoundsException e)
		{
			return;
		}
	}

	public void remove(int offs, int len) throws BadLocationException
	{

		super.remove(offs, len);
	}
}